package com.fany.views.waterwave;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.view.View;
import com.fany.fastsearcher.R;
import com.fany.utils.BitmapHelper;
import com.fany.utils.SystemUtils;

import java.util.Random;

public class WaterWaveView extends View implements Runnable
{
    private boolean _isWaving = false;

    private int _backgroundWidth;
    private int _backgroundHeight;

    private short[] waveEndBufffer;
    private short[] waveBeginBuffer;

    private int[] _resultPixelBuffer;
    private int[] _sourcePixelBuffer;


    public WaterWaveView(Context context, int resourceId)
    {
        super(context);
        Bitmap backgroundBitmap = BitmapHelper.loadBitmapResource(resourceId);
        backgroundBitmap  = Bitmap.createScaledBitmap(backgroundBitmap ,SystemUtils.getScreenWidth(), SystemUtils.getScreenHeight(), true);
        _backgroundWidth = backgroundBitmap.getWidth();
        _backgroundHeight = backgroundBitmap.getHeight();

        waveBeginBuffer = new short[_backgroundWidth * _backgroundHeight];
        waveEndBufffer = new short[_backgroundWidth * _backgroundHeight];
        _resultPixelBuffer = new int[_backgroundWidth * _backgroundHeight];
        _sourcePixelBuffer = new int[_backgroundWidth * _backgroundHeight];
        backgroundBitmap.getPixels(_sourcePixelBuffer, 0, _backgroundWidth, 0, 0, _backgroundWidth, _backgroundHeight);
        new Thread(this).start();
        render();
    }

    public void dropStone(Point center)
    {
        final int minRadius = 10;
        final int maxRadius = 100;
        final int minWeight = 50;
        final int maxWeight = 100;
        Random random = new Random();
        dropStone(center, minRadius + random.nextInt(maxRadius-minRadius), minWeight + random.nextInt(maxWeight-minWeight));
    }

    public void dropStone(Point center, int radius, int weight)
    {
        _isWaving = true;
        int left = center.x - radius;
        int right = center.x + radius;
        int top = center.y - radius;
        int bottom = center.y + radius;
        if (left < 0 || top < 0 || right > _backgroundWidth || bottom > _backgroundHeight)
        {
            return;
        }

        int squareRadius = radius * radius;
        for (int col = left; col < right; col++)
        {
            for (int row = top; row < bottom; row++)
            {
                if ((col - center.x) * (col - center.x) + (row - center.y) * (row - center.y) < squareRadius)
                {
                    waveBeginBuffer[_backgroundWidth * row + col] = (short) -weight;
                }
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        canvas.drawBitmap(_resultPixelBuffer, 0, _backgroundWidth, 0, 0, SystemUtils.getScreenWidth(), SystemUtils.getScreenHeight(), false, null);
    }

    public void run()
    {
        while (true)
        {
            try
            {
                Thread.sleep(40);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            if (_isWaving)
            {
                rippleSpread();
                render();
                postInvalidate();
            }
        }
    }

    private void rippleSpread()
    {
        boolean isWaving = false;
        for (int i = _backgroundWidth; i < _backgroundWidth * _backgroundHeight - _backgroundWidth; i++)
        {
            //波能扩散, X0'=a（X1+X2+X3+X4）+bX0, a = 1/2, b = -1
            int amplitude = (waveBeginBuffer[i - 1] + waveBeginBuffer[i + 1] + waveBeginBuffer[i - _backgroundWidth] + waveBeginBuffer[i + _backgroundWidth]) >> 1;
            waveEndBufffer[i] = (short) (amplitude - waveEndBufffer[i]);
            //波能衰减
            waveEndBufffer[i] -= waveEndBufffer[i] >> 5;
            if (!isWaving)
            {
                isWaving = waveEndBufffer[i] != 0;
            }
        }
        _isWaving = isWaving;
        //交换波能数据缓冲区
        short[] buffer = waveBeginBuffer;
        waveBeginBuffer = waveEndBufffer;
        waveEndBufffer = buffer;
    }

    private void render()
    {
        int index = _backgroundWidth;
        for (int row = 1; row < _backgroundHeight - 1; row++)
        {
            for (int col = 0; col < _backgroundWidth; col++)
            {
                int colOffset = waveBeginBuffer[index - 1] - waveBeginBuffer[index + 1];
                int rowOffset = waveBeginBuffer[index - _backgroundWidth] - waveBeginBuffer[index + _backgroundWidth];

                if ((row + rowOffset) < 0 || (row + rowOffset) > _backgroundHeight
                        || (col + colOffset) < 0 || (col + colOffset) > _backgroundWidth)
                {
                    index++;
                    continue;
                }
                int pos1 = _backgroundWidth * (row + rowOffset) + (col + colOffset);
                int pos2 = _backgroundWidth * row + col;
                if (++pos2 < _resultPixelBuffer.length && ++pos1 < _sourcePixelBuffer.length)
                {
                    _resultPixelBuffer[pos2] = _sourcePixelBuffer[pos1];
                }
                index++;
            }
        }
    }
}
